package com.starview.star.compiler.format;

import java.util.Map;
import java.util.Map.Entry;

import com.starview.platform.data.type.Location;
import com.starview.star.compiler.ast.IAttribute;
import com.starview.star.compiler.standard.StandardNames;

public class FormatPolicy
{
  int indentPolicy;
  int blankLinePolicy;
  int lineCommentColumnPolicy;
  boolean commentWrap;
  int commentWrapColumn;
  boolean breakBefore;
  boolean breakAfter;
  Location loc;

  FormatPolicy(Location loc, int indentPolicy, int blankLinePolicy, int lineCommentColumnPolicy, boolean commentWrap,
      int commentWrapColumn, boolean breakBefore, boolean breakAfter)
  {
    this.indentPolicy = indentPolicy;
    this.blankLinePolicy = blankLinePolicy;
    this.lineCommentColumnPolicy = lineCommentColumnPolicy;
    this.commentWrap = commentWrap;
    this.commentWrapColumn = commentWrapColumn;
    this.breakBefore = breakBefore;
    this.breakAfter = breakAfter;
    this.loc = loc;
  }

  FormatPolicy()
  {
    this(Location.nullLoc, 0, 1, 50, false, 80, false, false);
  }

  FormatPolicy adjustPolicies(Location loc, Map<String, IAttribute> attributes)
  {
    int indent = indentPolicy;
    int blankLine = blankLinePolicy;
    int lineComment = lineCommentColumnPolicy;
    boolean wrap = commentWrap;
    int columnWrap = commentWrapColumn;
    boolean before = breakBefore;
    boolean after = breakAfter;

    for (Entry<String, IAttribute> entry : attributes.entrySet())
    {
      String att = entry.getKey();
      if (att.equals(StandardNames.FMT_INDENT))
        indent = ((NumericAttribute) entry.getValue()).apply(indentPolicy);
      else if (att.equals(StandardNames.FMT_LINES))
        blankLine = ((NumericAttribute) entry.getValue()).apply(blankLinePolicy);
      else if (att.equals(StandardNames.FMT_COMMENT_COLUMN))
        lineComment = ((NumericAttribute) entry.getValue()).apply(lineCommentColumnPolicy);
      else if (att.equals(StandardNames.FMT_COMMENT_WRAP))
        wrap = ((BooleanAttribute) entry.getValue()).apply(commentWrap);
      else if (att.equals(StandardNames.FMT_WRAP_COLUMN))
        columnWrap = ((NumericAttribute) entry.getValue()).apply(commentWrapColumn);
      else if (att.equals(StandardNames.FMT_COMMENT_COLUMN))
        lineComment = ((NumericAttribute) entry.getValue()).apply(lineCommentColumnPolicy);
      else if (att.equals(StandardNames.FMT_BREAK_BEFORE))
        before = ((BooleanAttribute) entry.getValue()).apply(before);
      else if (att.equals(StandardNames.FMT_BREAK_AFTER))
        after = ((BooleanAttribute) entry.getValue()).apply(after);
    }
    return new FormatPolicy(loc, indent, blankLine, lineComment, wrap, columnWrap, before, after);
  }

  boolean expiredLocation(int ix)
  {
    return loc.getCharCount() >= 0 && loc.getCharCount() + loc.getLength() <= ix;
  }

  @Override
  public String toString()
  {
    return "{ indent=" + indentPolicy + ", lines=" + blankLinePolicy + ", breakBefore: " + breakBefore
        + ", breakAfter: " + breakAfter + "}";
  }
}